package ae.pcfc.cldos.online.gs.service.client.provider;


import java.util.ArrayList;
import java.util.GregorianCalendar;
import java.util.List;

import javax.annotation.Resource;
import javax.xml.datatype.DatatypeConfigurationException;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;

import org.dozer.DozerBeanMapper;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.ws.WebServiceMessage;
import org.springframework.ws.client.core.WebServiceMessageCallback;
import org.springframework.ws.client.core.WebServiceTemplate;
import org.springframework.ws.soap.SoapMessage;

import ae.pcfc.cldos.online.gs.ConstantsGS;
import ae.pcfc.cldos.online.gs.service.client.BaseGS;
import ae.pcfc.cldos.online.gs.service.client.vo.BankGuaranteeOperationVO;
import ae.pcfc.cldos.online.gs.service.client.vo.GSFinancialDataVO;
import ae.pcfc.cldos.online.gs.service.client.vo.NotificationVO;
import ae.pcfc.cldos.online.gs.service.client.vo.StepCommentsVO;
import ae.pcfc.cldos.online.gs.service.client.vo.WarningCommentsVO;
import ae.pcfc.cldos.online.gs.service.types.AddBankGuaranteeOperation;
import ae.pcfc.cldos.online.gs.service.types.ArrayOfDTORemark;
import ae.pcfc.cldos.online.gs.service.types.ArrayOfString;
import ae.pcfc.cldos.online.gs.service.types.CancelAppRequest;
import ae.pcfc.cldos.online.gs.service.types.CancelAppRequestResponse;
import ae.pcfc.cldos.online.gs.service.types.DTORemark;
import ae.pcfc.cldos.online.gs.service.types.DTOStepAction;
import ae.pcfc.cldos.online.gs.service.types.DTOStepComment;
import ae.pcfc.cldos.online.gs.service.types.FinancialData;
import ae.pcfc.cldos.online.gs.service.types.GetClientMedicalType;
import ae.pcfc.cldos.online.gs.service.types.GetClientMedicalTypeResponse;
import ae.pcfc.cldos.online.gs.service.types.GetFinancialData;
import ae.pcfc.cldos.online.gs.service.types.GetFinancialDataResponse;
import ae.pcfc.cldos.online.gs.service.types.GetNextAppID;
import ae.pcfc.cldos.online.gs.service.types.GetNextAppIDResponse;
import ae.pcfc.cldos.online.gs.service.types.GetWFCurrentTaskStatus;
import ae.pcfc.cldos.online.gs.service.types.GetWFCurrentTaskStatusResponse;
import ae.pcfc.cldos.online.gs.service.types.GetWarningRemarksList;
import ae.pcfc.cldos.online.gs.service.types.GetWarningRemarksListResponse;
import ae.pcfc.cldos.online.gs.service.types.InsertStepComments;
import ae.pcfc.cldos.online.gs.service.types.InsertStepCommentsResponse;
import ae.pcfc.cldos.online.gs.service.types.IsApplicationInProcess;
import ae.pcfc.cldos.online.gs.service.types.IsApplicationInProcessResponse;
import ae.pcfc.cldos.online.gs.service.types.RejectAppRequest;
import ae.pcfc.cldos.online.gs.service.types.RejectAppRequestResponse;
import ae.pcfc.cldos.online.gs.service.types.SendClientEmail;
import ae.pcfc.cldos.online.gs.service.types.SendClientEmailResponse;
import ae.pcfc.cldos.online.gs.service.types.SendNotificationAndClientEmail;
import ae.pcfc.cldos.online.gs.service.types.SendNotificationAndClientEmailResponse;
import ae.pcfc.cldos.online.gs.service.types.SetAppMetaWFStatus;
import ae.pcfc.cldos.online.gs.service.types.SetAppMetaWFStatusResponse;
import ae.pcfc.cldos.online.gs.service.types.SetClientMedicalType;
import ae.pcfc.cldos.online.gs.service.types.SetClientMedicalTypeResponse;
import ae.pcfc.cldos.online.gs.service.types.SetIncidentId;
import ae.pcfc.cldos.online.gs.service.types.SetIncidentIdResponse;


public abstract class BaseGSImpl implements BaseGS {

	protected WebServiceTemplate wsTemplateGS;
	protected String formsAppURL;
	
	private DozerBeanMapper mapper;
	
	public void setMapper(DozerBeanMapper mapper) {
		this.mapper = mapper;
	}
	
	@Value("${GovtSysGS}")
	String classURIValue = ConstantsGS.GS_WS_ENDPOINT;
	
	private static DatatypeFactory df = null;     
	static {         
		try {             
			df = DatatypeFactory.newInstance();         
		} catch (DatatypeConfigurationException dce) {             
			throw new IllegalStateException(                 
					"Exception while obtaining DatatypeFactory instance", dce);         
		}     
	}        
	/*** Converts a java.util.Date into an instance of XMLGregorianCalendar      *      * 
	@param date Instance of java.util.Date or a null reference      
	* @return XMLGregorianCalendar instance whose value is based upon the      
	*  value in the date parameter. If the date parameter is null then      *  this method will simply return null.      */    
	public static XMLGregorianCalendar asXMLGregorianCalendar(java.util.Date date) {
		if (date == null) {
			return null;
		} else {
			GregorianCalendar gc = new GregorianCalendar();
			gc.setTimeInMillis(date.getTime());
			return df.newXMLGregorianCalendar(gc);
		}
	} 

	/**
	 * @param formsAppURL the formsAppURL to set
	 */
	@Resource(name = "formsAppURL")
	public void setFormsAppURLGS(String formsAppURL) {
		this.formsAppURL = formsAppURL;
	}
	/**
	 * @param wsTemplateGS
	 *            the wsTemplateGS to set
	 */
	@Resource(name = "wsTemplateGS")
	public void setWsTemplateGS(WebServiceTemplate wsTemplateGS) {
		this.wsTemplateGS = wsTemplateGS;
	}
	
	
	
	/*//**
	 * @param none
	 * @author akhader
	 * @return  List<FNPCatalogVO>
	 * method to fetch the catalog desc from FNp through web service
	 *//*
*/	
	public GSFinancialDataVO retreiveFinancialData(String clientLicenseNumber){
		GSFinancialDataVO gSFinancialDataVO = new GSFinancialDataVO();
		//setting the parameters
		GetFinancialData getFinancialData = new GetFinancialData();
		getFinancialData.setClientLicenseNumber(clientLicenseNumber);
		
		//calling the FNP getcatalog method
		GetFinancialDataResponse response = (GetFinancialDataResponse) wsTemplateGS
				.marshalSendAndReceive(classURIValue,getFinancialData,
						new WebServiceMessageCallback() {
							public void doWithMessage(WebServiceMessage message) {
								((SoapMessage) message)
										.setSoapAction(ConstantsGS.GET_FINANCIAL_DATA_SOAP_ACTION);
							}
						});
		FinancialData financialData = response.getGetFinancialDataResult();
		
		mapper.map(financialData, gSFinancialDataVO);
	
		return gSFinancialDataVO;
	}
	
	public boolean sendNotificationAndClientEmail(NotificationVO notificationVO){
		SendNotificationAndClientEmail sendNotificationAndClientEmail = 
				new SendNotificationAndClientEmail();
		
		ArrayOfString attchIds = new ArrayOfString();
		attchIds.getString().addAll(notificationVO.getTransferedAttachmentsIds());
		
		sendNotificationAndClientEmail.setAttachmentIds(attchIds);
		sendNotificationAndClientEmail.setClientLicenseNumber(notificationVO.getCoLicNo());
		sendNotificationAndClientEmail.setMessageBody(notificationVO.getMessage());
		sendNotificationAndClientEmail.setOnlineAppId(notificationVO.getOnlineAppId());
		sendNotificationAndClientEmail.setSubject(notificationVO.getSubject());
		sendNotificationAndClientEmail.setMessageBodyArabic(notificationVO.getMessageAr());
		sendNotificationAndClientEmail.setSubjectArabic(notificationVO.getSubjectAr());
		
		SendNotificationAndClientEmailResponse response = (SendNotificationAndClientEmailResponse) wsTemplateGS
				.marshalSendAndReceive(classURIValue,sendNotificationAndClientEmail,
						new WebServiceMessageCallback() {
							public void doWithMessage(WebServiceMessage message) {
								((SoapMessage) message)
										.setSoapAction(ConstantsGS.SEND_NOTIFICATION_AND_EMAIL_SOAP_ACTION);
							}
						});
		
		return response.isSendNotificationAndClientEmailResult();
		
	}
	
	public boolean sendEmails(NotificationVO notificationVO){
		SendClientEmail sendClientEmail = 
				
				new SendClientEmail();
		
		ArrayOfString attchIds = new ArrayOfString();
		attchIds.getString().addAll(notificationVO.getTransferedAttachmentsIds());
		
		sendClientEmail.setAttachmentIds(attchIds);
		sendClientEmail.setMessageBody(notificationVO.getMessage());
		sendClientEmail.setSubject(notificationVO.getSubject());
		
		ArrayOfString arrayOfString = new ArrayOfString();
		arrayOfString.getString().addAll(notificationVO.getEmailsList());
		sendClientEmail.setToList(arrayOfString);
		
		SendClientEmailResponse response = (SendClientEmailResponse) wsTemplateGS
				.marshalSendAndReceive(classURIValue,sendClientEmail,
						new WebServiceMessageCallback() {
							public void doWithMessage(WebServiceMessage message) {
								((SoapMessage) message)
										.setSoapAction(ConstantsGS.SEND_CLIENT_EMAIL_SOAP_ACTION);
							}
						});
		
		return response.isSendClientEmailResult();
		
	}
	
	public String getNextOfflineAppId(String processCode){
		GetNextAppID getNextAppID = new GetNextAppID();
		getNextAppID.setProcessCode(processCode);
		
		GetNextAppIDResponse response = (GetNextAppIDResponse) wsTemplateGS
				.marshalSendAndReceive(classURIValue,getNextAppID,
						new WebServiceMessageCallback() {
							public void doWithMessage(WebServiceMessage message) {
								((SoapMessage) message)
										.setSoapAction(ConstantsGS.GET_NEXT_APPID_SOAP_ACTION);
							}
						});
		
		return response.getGetNextAppIDResult();
	}
	
	public void setClientMedicalType(String companyLicenseNo, String medicalType) {
		
		SetClientMedicalType setClientMediaclType = new SetClientMedicalType();
		setClientMediaclType.setCompanyLicenseNo(companyLicenseNo);
		setClientMediaclType.setMedicalType(medicalType);
		
		@SuppressWarnings("unused")
		SetClientMedicalTypeResponse response = (SetClientMedicalTypeResponse) wsTemplateGS
				.marshalSendAndReceive(classURIValue,setClientMediaclType,
						new WebServiceMessageCallback() {
							public void doWithMessage(WebServiceMessage message) {
								((SoapMessage) message)
										.setSoapAction(ConstantsGS.SET_CLIENT_MEDICAL_TYPE);
							}
						});
						
		return;						
	}
	
	
	public String getClientMedicalType(String companyLicenseNo) {
		
		GetClientMedicalType getClientMediaclType = new GetClientMedicalType();
		getClientMediaclType.setCompanyLicenseNo(companyLicenseNo);
		
		GetClientMedicalTypeResponse response = (GetClientMedicalTypeResponse) wsTemplateGS
				.marshalSendAndReceive(classURIValue,getClientMediaclType,
						new WebServiceMessageCallback() {
							public void doWithMessage(WebServiceMessage message) {
								((SoapMessage) message)
										.setSoapAction(ConstantsGS.GET_CLIENT_MEDICAL_TYPE);
							}
						});
			
		return response.getGetClientMedicalTypeResult();						
	}
	
	public boolean cancelAppRequest(String offlineAppId){
		CancelAppRequest cancelAppRequest = new CancelAppRequest();
		cancelAppRequest.setOfflineAppId(offlineAppId);
		
		CancelAppRequestResponse response = (CancelAppRequestResponse) wsTemplateGS
				.marshalSendAndReceive(classURIValue,cancelAppRequest,
						new WebServiceMessageCallback() {
							public void doWithMessage(WebServiceMessage message) {
								((SoapMessage) message)
										.setSoapAction(ConstantsGS.CANCEL_APP_REQUEST);
							}
						});
		
		return response.isCancelAppRequestResult();
		
	}
	
	public boolean rejectAppRequest(String offlineAppId){
		RejectAppRequest rejectAppRequest = new RejectAppRequest();
		rejectAppRequest.setOfflineAppId(offlineAppId);
		
		RejectAppRequestResponse response = (RejectAppRequestResponse) wsTemplateGS
				.marshalSendAndReceive(classURIValue,rejectAppRequest,
						new WebServiceMessageCallback() {
							public void doWithMessage(WebServiceMessage message) {
								((SoapMessage) message)
										.setSoapAction(ConstantsGS.REJECT_APP_REQUEST);
							}
						});
		
		return response.isRejectAppRequestResult();
		
	}
	
	public void bankGuaranteeOperation(BankGuaranteeOperationVO bankGuaranteeOperationVO ){
		AddBankGuaranteeOperation addBankGuaranteeOperation = new AddBankGuaranteeOperation();
		mapper.map(bankGuaranteeOperationVO, addBankGuaranteeOperation);
		
		wsTemplateGS.marshalSendAndReceive(classURIValue,addBankGuaranteeOperation,
						new WebServiceMessageCallback() {
							public void doWithMessage(WebServiceMessage message) {
								((SoapMessage) message)
										.setSoapAction(ConstantsGS.BANK_GUARANTEE_OPERATION);
							}
						});
	}
	
	public String getWfStatus(String clientRefNo){
		GetWFCurrentTaskStatus getWFCurrentTaskStatus =  new GetWFCurrentTaskStatus();
		getWFCurrentTaskStatus.setOfflineAppId(clientRefNo);
		GetWFCurrentTaskStatusResponse  getWFCurrentTaskStatusResponse = (GetWFCurrentTaskStatusResponse) wsTemplateGS.marshalSendAndReceive(classURIValue,getWFCurrentTaskStatus,
				new WebServiceMessageCallback() {
					public void doWithMessage(WebServiceMessage message) {
						((SoapMessage) message)
								.setSoapAction(ConstantsGS.WF_STATUS_REQUEST);
					}
				});
		String response = getWFCurrentTaskStatusResponse.getGetWFCurrentTaskStatusResult();
		if(response == null || response.equals(ConstantsGS.WF_STATUS_EMPTY)){
			response = ConstantsGS.WF_STATUS_NA;
		}
		return response;
	}
	
	public boolean setIncidentId(String offlineAppId, String incidentId){
		SetIncidentId setIncidentId =  new SetIncidentId();
		setIncidentId.setIncidentId(incidentId);
		setIncidentId.setOfflineAppId(offlineAppId);
		SetIncidentIdResponse  response = (SetIncidentIdResponse) wsTemplateGS.marshalSendAndReceive(classURIValue,setIncidentId,
				new WebServiceMessageCallback() {
					public void doWithMessage(WebServiceMessage message) {
						((SoapMessage) message)
								.setSoapAction(ConstantsGS.SET_INCIDENT_ID);
					}
				});
		
		return response.isSetIncidentIdResult();
	}
	/**
	 * @param offlineAppId
	 * @param wfStatus
	 */
	public void updateAppReqWorkFlowStatus(String offlineAppId,String wfStatus){
		SetAppMetaWFStatus setAppMetaWFStatus = new SetAppMetaWFStatus();
		setAppMetaWFStatus.setOfflineAppId(offlineAppId);
		setAppMetaWFStatus.setWFStatus(wfStatus);
		
		SetAppMetaWFStatusResponse response = (SetAppMetaWFStatusResponse) wsTemplateGS
				.marshalSendAndReceive(classURIValue,setAppMetaWFStatus,
						new WebServiceMessageCallback() {
							public void doWithMessage(WebServiceMessage message) {
								((SoapMessage) message)
										.setSoapAction(ConstantsGS.SET_WF_STATUS_APP_REQUEST);
							}
						});
		System.out.println("response"+response.toString());
	}
	/**
	 * @param stepCommentsVO
	 */
	public void insertStepComments(StepCommentsVO stepCommentsVO){
		DTOStepComment comment = new DTOStepComment();
		comment.setApplicationId(stepCommentsVO.getApplicationId());
		comment.setCommentBy(stepCommentsVO.getCommentBy());
		comment.setCommentDate(asXMLGregorianCalendar(stepCommentsVO.getCommentDate()));
		comment.setCommentDesc(stepCommentsVO.getCommentDesc());
		comment.setCommentStatus(ConstantsGS.COMPLETED);
		comment.setProcessCode(stepCommentsVO.getProcessCode());
		comment.setProcessStepCode(ConstantsGS.PROCESS_CODE_PAYMENT_APPRVD);
		
		DTOStepAction dtoStepAction = new DTOStepAction();
		dtoStepAction.setActionDate(asXMLGregorianCalendar(stepCommentsVO.getCommentDate()));
		dtoStepAction.setApplicationId(stepCommentsVO.getApplicationId());
		dtoStepAction.setProcessCode(stepCommentsVO.getProcessCode());
		dtoStepAction.setProcessStepCode(ConstantsGS.PROCESS_CODE_PAYMENT_APPRVD);
		dtoStepAction.setActionUser(stepCommentsVO.getCommentBy());
		dtoStepAction.setActionDesc(stepCommentsVO.getActionDesc());
		
		
		InsertStepComments insertStepComments = new InsertStepComments();
		insertStepComments.setDtoStepComments(comment);
		insertStepComments.setDtoSA(dtoStepAction);
		
		
		InsertStepCommentsResponse response = (InsertStepCommentsResponse) wsTemplateGS
				.marshalSendAndReceive(classURIValue,insertStepComments,
						new WebServiceMessageCallback() {
							public void doWithMessage(WebServiceMessage message) {
								((SoapMessage) message)
										.setSoapAction(ConstantsGS.INSERT_STEP_COMMENTS);
							}
						});
		System.out.println("response"+response.isInsertStepCommentsResult());
	}
	
	/**
	 * @param licNo
	 * @return
	 */
	public List<WarningCommentsVO>  getWarningRemarks(String licNo){
		List<WarningCommentsVO> warningCommentsVOs = new ArrayList<WarningCommentsVO>();
		GetWarningRemarksList getWarningRemarksList = new GetWarningRemarksList();
		getWarningRemarksList.setClientLicenseNumber(licNo);
		
		GetWarningRemarksListResponse response = (GetWarningRemarksListResponse) wsTemplateGS
				.marshalSendAndReceive(classURIValue,getWarningRemarksList,
						new WebServiceMessageCallback() {
							public void doWithMessage(WebServiceMessage message) {
								((SoapMessage) message)
										.setSoapAction(ConstantsGS.GET_WARNING_REMARK);
							}
						});
		if(response!= null){
			ArrayOfDTORemark arrayOfDTORemark = response.getGetWarningRemarksListResult();
			if(arrayOfDTORemark.getDTORemark() != null){
				for(DTORemark dtoRemark:arrayOfDTORemark.getDTORemark()){
					WarningCommentsVO warningCommentsVO= new WarningCommentsVO();
					warningCommentsVO.setComment(dtoRemark.getComment());
					warningCommentsVO.setDescEn(dtoRemark.getDescEn());
					warningCommentsVOs.add(warningCommentsVO);
				}
			}
		}
		return warningCommentsVOs;
	}
	
	/**
	 * @param processCode
	 * @param empId
	 * @param visitorId
	 * @return
	 */
	public boolean isRequestExist(String processCode,String empId, String visitorId){
		boolean flag = true;
		
		IsApplicationInProcess isApplicationInProcess = new IsApplicationInProcess();
		isApplicationInProcess.setEmployeeId(empId);
		isApplicationInProcess.setProcessCode(processCode);
		isApplicationInProcess.setVisitorId(visitorId);
		
		IsApplicationInProcessResponse response = (IsApplicationInProcessResponse) wsTemplateGS
				.marshalSendAndReceive(classURIValue,isApplicationInProcess,
						new WebServiceMessageCallback() {
							public void doWithMessage(WebServiceMessage message) {
								((SoapMessage) message)
										.setSoapAction(ConstantsGS.IS_REQ_IN_PROGRESS);
							}
						});
		if(response != null){
			flag = response.isIsApplicationInProcessResult();
		}
		return flag;
	}

}
